#include<iostream>
#include<string>

// 抽象产品接口
class ProductA {
public:
    virtual void show() = 0;
};

class ProductB {
public:
    virtual void show() = 0;
};

// 具体产品实现
class ConcreteProductA1 : public ProductA {
public:
    void show() override {
        std::cout << "ConcreteProductA1"<< std::endl;
    }
};

class ConcreteProductA2 : public ProductA {
public:
    void show() override {
        std::cout << "ConcreteProductA2"<< std::endl;
    }
};

class ConcreteProductB1 : public ProductB {
public:
    void show() override {
        std::cout << "ConcreteProductB1"<< std::endl;
    }
};

class ConcreteProductB2 : public ProductB {
public:
    void show() override {
        std::cout << "ConcreteProductB2"<< std::endl;
    }
};

// 抽象工厂接口
class AbstractFactory {
public:
    virtual ProductA* createProductA() = 0;
    virtual ProductB* createProductB() = 0;
};

// 具体工厂实现
class ConcreteFactory1 : public AbstractFactory {
public:
    ProductA* createProductA() override {
        return new ConcreteProductA1();
    }

    ProductB* createProductB() override {
        return new ConcreteProductB1();
    }
};

class ConcreteFactory2 : public AbstractFactory {
public:
    ProductA* createProductA() override {
        return new ConcreteProductA2();
    }

    ProductB* createProductB() override {
        return new ConcreteProductB2();
    }
};

int main() {
    // 使用工厂1创建产品
    AbstractFactory* factory1 = new ConcreteFactory1();
    ProductA* productA1 = factory1->createProductA();
    ProductB* productB1 = factory1->createProductB();
    productA1->show();
    productB1->show();

    // 使用工厂2创建产品
    AbstractFactory* factory2 = new ConcreteFactory2();
    ProductA* productA2 = factory2->createProductA();
    ProductB* productB2 = factory2->createProductB();
    productA2->show();
    productB2->show();

    // 释放内存
    delete productA1;
    delete productB1;
    delete productA2;
    delete productB2;
    delete factory1;
    delete factory2;

    return 0;
}

/* Running:
ConcreteProductA1
ConcreteProductB1
ConcreteProductA2
ConcreteProductB2
 */